﻿using System;
using System.IO;
using System.Reflection;
using System.Xml.Linq;
using System.Net;
using System.Windows.Browser;
using SilverQuery;

namespace SilverPortal
{
	/// <summary>
	/// Base class for all portal modules.
	/// </summary>
	public abstract class SilverPortalModule : SilverQueryObject
	{
		public ModuleConfig Config
		{
			get;
			internal set;
		}

		protected internal jQuery Container
		{
			get;
			internal set;
		}

		protected internal Logger Log
		{
			get;
			internal set;
		}

		protected internal PortalState State
		{
			get;
			internal set;
		}

		protected jQuery GetHeaderRightContent()
		{
			return @q("div.header div.right", this.Container.closest("div.module"));
		}

		/// <summary>
		/// Has this module already been loaded?
		/// </summary>
		public bool Loaded
		{
			get;
			private set;
		}

		protected void DoneLoading()
		{
			HideLoading();
			this.Loaded = true;
		}

		/// <summary>
		/// Perform any one time initialization.
		/// </summary>
		protected virtual void Init()
		{
		}

		internal void LoadInternal()
		{
			try
			{
				this.Load();
			}
			catch (Exception e)
			{
				DisplayError("Error loading module", e);
			}
		}

		/// <summary>
		/// Load the module.
		/// </summary>
		protected abstract void Load();

		protected void DisplayError(string message, Exception error)
		{
			this.Loaded = true;
			DisplayError(message, error, this.Container);
		}

		internal static void DisplayError(string message, Exception error, jQuery container)
		{
			container.empty();

			var errorTemplate = new jQuery(@"<div class=""error""><h3 class=""message"" /><p class=""exception"" /></div>");

			new jQuery("h3", errorTemplate).html("Module Error: " + message);
			new jQuery("p.exception", errorTemplate).html(error.ToString());
			errorTemplate.appendTo(container);
		}

		/// <summary>
		/// Hide the loading message.
		/// </summary>
		protected void HideLoading()
		{
			@q("div.loading", this.Container).remove();
		}

		/// <summary>
		/// Set the sub-title text which in right-aligned in the title bar.
		/// </summary>
		/// <param name="text"></param>
		protected void SetSubTitle(string text)
		{
			@q("div.header>div.right", this.Container.closest(".module")).html(text);
		}

		/// <summary>
		/// Register a css style block read from an embedded resource.
		/// </summary>
		/// <param name="cssResource"></param>
		/// <remarks>The </remarks>
		protected void RegisterCssResource(string cssResource)
		{
			var assembly = Assembly.GetCallingAssembly();
			string css;
			using (var sr = new StreamReader(assembly.GetManifestResourceStream(cssResource)))
			{
				css = sr.ReadToEnd();
			}

			var styleElem = @q("<style />").attr("type", "text/css")
				.attr("title", "silverPortal")
				.html(css);

			@q("style[title='silverPortal']:last").after(styleElem);
		}
	}
}
